package com.lik888.web1.filter;

import cn.hutool.jwt.JWTUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;

import com.lik888.web1.entity.UserProductiontable;
import com.lik888.web1.entity.UserproducionConnectiontable;
import com.lik888.web1.mapper.UserProductiontableMapper;
import com.lik888.web1.mapper.UserproducionConnectiontableMapper;
import com.lik888.web1.utils.JwtTool;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.security.Security;
import java.util.ArrayList;
import java.util.List;

@RequiredArgsConstructor
@Component
public class JWTAuthenticationfilter  extends OncePerRequestFilter {
//此处因为Lombok失效所以手动注入
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserproducionConnectiontableMapper userproducionConnectiontableMapper;
    @Autowired
    private UserProductiontableMapper userProductiontableMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private JwtTool jwtTool;


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String requestURI = request.getRequestURI();
        //判断
        if(requestURI.equals("/user/login")){
            filterChain.doFilter(request, response);
            return;
        }

        if(requestURI.equals("/auth/reader")){
            filterChain.doFilter(request, response);
            return;
        }

        if(requestURI.equals("/auth/callback")){
            filterChain.doFilter(request, response);
            return;
        }

        if(requestURI.equals("/user/register")){
            filterChain.doFilter(request, response);
            return;
        }
        if(requestURI.equals("/user/forgetemail")){
            filterChain.doFilter(request, response);
            return;
        }

        if(requestURI.equals("/user/returncode")){
            filterChain.doFilter(request, response);
            return;
        }

        if(requestURI.equals("/user/resetpassword")){
            filterChain.doFilter(request, response);
            return;
        }



        String requestURI1 = request.getRequestURI();
        String contextPath = request.getContextPath(); // 获取上下文路径（如 "/web1"）
        System.out.println("上下文路径：" + contextPath + "，请求路径：" + requestURI1);

        String authorization = request.getHeader("Authorization");
        if(!StringUtils.hasText(authorization)){
            throw new RuntimeException("Authorization header is empty");
        }
        Long l = jwtTool.parseToken(authorization);
        System.out.println(l);

        String token = stringRedisTemplate.opsForValue().get("KingyoungMALL:user:"+l);
        if(!StringUtils.hasText(token)){
            throw new RuntimeException("token is empty");
        }


        //TODO 从数据库中获取权限
        List<UserproducionConnectiontable> connectiontables = userproducionConnectiontableMapper.selectList(new QueryWrapper<UserproducionConnectiontable>().eq("user_id", l));
        //判断是否有权限
        if(connectiontables.isEmpty()){
            throw new RuntimeException("user has no permission");
        }
        //1.2 从连接表中获取权限ID
        List<Integer> productionIds = connectiontables.stream().map(UserproducionConnectiontable::getProductionId).toList();
        //1.3 从权限表中获取权限
        List<UserProductiontable> productiontables = userProductiontableMapper.selectBatchIds(productionIds);
        //1.4 从权限表中获取权限名
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        productiontables.forEach(productiontable -> {
            authorities.add(new SimpleGrantedAuthority(productiontable.getProduction()));
        });
        System.out.println(authorities);

        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(l,null, authorities);
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);

        filterChain.doFilter(request, response);
    }
}

//判断PreAuthorize 是否绑定了 一人一权限 authentication 即上述代码中的 authenticationToken（当前登录用户的认证信息）。
//authentication.principal 即 authenticationToken 的第一个参数（userDetails 对象）。
//因此，authentication.principal.id 就是 userDetails 中的 id 字段。
//这里的token 如果是换成public class UserDetailsImpl implements UserDetails {
//    private Long id; // 用户ID
//    private String username;
//    // 构造方法、getter/setter 等
//    public Long getId() { return id; }
//}
//
//// 创建认证令牌时传入该对象
//UserDetailsImpl userDetails = new UserDetailsImpl(123L, "testUser"); // id=123
//UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
//    userDetails, null, authorities
//);
//对象的情况下 就需要 authentication.principal.getId() 来获取用户ID。
